/***************************************************
> Copyright (C) 2024 ==KINGYI== All rights reserved.
> File Name: server.c
> Author:cjy
> Mail: 
> Created Time: 2024年08月16日 星期五 10时46分28秒
***************************************************/

#include "queue.h"
#include "threadpool.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "cJSON.h"
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

int flag = 1;

// 信号处理函数
void fun(int sig) {
    flag = 0;
    printf("关闭成功\n");
}

// 生产者线程
void *fun1(void *arg) {
    THP *p = (THP *)arg;

    DAT data;
    int sock = 0;
    int ret = 0;

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("socket");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(6666);
    addr.sin_addr.s_addr = inet_addr("192.168.198.128");

    ret = bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1) {
        perror("bind");
        exit(-1);
    }

    while (flag == 1) {
        listen(sock, 5);

        data.listenfd = accept(sock, NULL, NULL);
        if (data.listenfd == -1) {
            perror("accept");
            exit(-1);
        }

        pthread_mutex_lock(&p->mutex);
        push(data, p->que);
        pthread_mutex_unlock(&p->mutex);

        sem_post(&p->semr);
        printf("入队: %d\n", data.listenfd);
    }

    close(sock);
    printf("生产者结束\n");
}

// 消费者线程
void *fun2(void *arg) {
    THP *p = (THP *)arg;
    DAT dat;
    int ret = 0;
    char buf[1024] = {0};
    char *dest = NULL;
    struct number num;
    memset(&num, 0, sizeof(num));

    cJSON *json = NULL;

    while (flag == 1) {
        sem_wait(&p->semr);
        pthread_mutex_lock(&p->mutex);

        if (!isempty(p->que)) {
            dat = front(p->que);
            sem_post(&p->semr);
            pthread_mutex_unlock(&p->mutex);

            printf("%ld ", pthread_self() % 100);
	while(1){
            ret = recv(dat.listenfd, buf, 1024, 0);
            if (ret == -1) {
                perror("recv");
                break;
            }
            puts(buf);

            json = cJSON_Parse(buf);
            if (!json) {
                printf("无法解析 JSON\n");
                continue;
            }

            cJSON *node = cJSON_GetObjectItem(json, "type");
            if (node == NULL) {
                printf("can't find type\n");
                cJSON_Delete(json);
                continue;
            }
            if (node->type == cJSON_Number) {
                dat.type = node->valueint;
            }

            node = cJSON_GetObjectItem(json, "count");
            if (node == NULL) {
                printf("can't find count\n");
                cJSON_Delete(json);
                continue;
            }
            if (node->type == cJSON_String) {
                strcpy(dat.count, node->valuestring);
            }

            node = cJSON_GetObjectItem(json, "num1");
            if (node == NULL) {
                printf("can't find num1\n");
                cJSON_Delete(json);
                continue;
            }
            if (node->type == cJSON_Number) {
                dat.num1 = node->valuedouble;
            }

            node = cJSON_GetObjectItem(json, "num2");
            if (node == NULL) {
                printf("can't find num2\n");
                cJSON_Delete(json);
                continue;
            }
            if (node->type == cJSON_Number) {
                dat.num2 = node->valuedouble;
            }

            switch (dat.type) {
                case 1:
                    num.sum = dat.num1 + dat.num2;
                    printf("num.sum:%f\n", num.sum);
                    break;
                case 2:
                    num.sum = dat.num1 - dat.num2;
                    printf("num.sum:%f\n", num.sum);
                    break;
                case 3:
                    num.sum = dat.num1 * dat.num2;
                    printf("num.sum:%f\n", num.sum);
                    break;
                case 4:
                    if (dat.num2 != 0) {
                        num.sum = dat.num1 / dat.num2;
                        printf("num.sum:%f\n", num.sum);
                    } else {
                        printf("除数不能为零\n");
                    }
                    break;
                default:
                    printf("未知的操作类型\n");
                    break;
            }

            json = cJSON_CreateObject();
            cJSON_AddNumberToObject(json, "sum", num.sum);
            dest = cJSON_Print(json);
            puts(dest);

            ret = send(dat.listenfd, dest, strlen(dest), 0);
            if (ret == -1) {
                perror("send");
                break;
            }
            cJSON_Delete(json);
            free(dest);
                pthread_mutex_lock(&p->mutex); // 再次锁住队列
                pop(p->que); // 移除当前处理的客户端连接
                pthread_mutex_unlock(&p->mutex);
                break; // 跳出内层循环，回到外层循环继续等待新任务
            }
        } else {
            pthread_mutex_unlock(&p->mutex); // 如果队列为空，则解锁并等待信号
        }
        sem_post(&p->semr); // 释放信号量，表明已完成一个任务
}
    close(dat.listenfd);
    printf("消费者 %ld 结束\n", pthread_self() % 100);
}

int main() {
    int threads = 20;
    int queue_length = 100;

    // 创建线程池
    THP *p = create_threadpool(threads, queue_length, fun2);

    // 创建生产者
    pthread_t tid1 = 0;
    int ret = pthread_create(&tid1, NULL, fun1, p);
    if (ret != 0) {
        perror("pthread_create");
        exit(-1);
    }

    // 设置 SIGINT 信号处理函数
    signal(SIGINT, fun);

    // 主循环
    while (1) {
        printf("%d", flag);
        if (flag == 0) {
            break;
        }
        sleep(1);
    }

    // 等待所有线程完成
    destroy_threadpool(p);

    // 检查队列是否为空
    if (isempty(p->que) != 0) {
        delLinkMem(p->que);
    }
    printf("队列为空\n");

    // 等待生产者线程完成
    pthread_join(tid1, NULL);

    return 0;
}


